/**
 * 
 */
package com.utils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

/**
 * @author SGJT
 *
 */
public class WeixinServlet extends HttpServlet {
	
	public static final Log log = LogFactory.getLog(WeixinServlet.class);
	
	public static String TOKEN="weixin";
	public Map dataModel=null;
	private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
	'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
   /**
	 *
	 */
	private static final long serialVersionUID = 1L;
	
	

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
    	dataModel=new HashMap();
    	/*prefix = getInitParameter("prefix");
    	dataModel.put("prefix", prefix);
    	source_dir=getInitParameter("source_dir");
    	dataModel.put("source_dir", source_dir);
    	sys_id = getInitParameter("sys_id");
    	dataModel.put("SYS_ID", sys_id);*/
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        if(request.getParameter("echostr")==null){
        	try{
        		if("toToken".equals(request.getParameter("toToken"))){
        			//修改token值
        			if(request.getParameter("Token")!=null){
        				WeixinServlet.TOKEN=request.getParameter("Token");
        			}else{
        				log.error("Failed", new Exception("change Token failed, request.getParameter(\"Token\")=null"));
        			}
        			response.getWriter().write("WeixinServlet.TOKEN="+WeixinServlet.TOKEN);
                }else{
                	doResponseMsg(request,response);
                }
        	}catch(Exception ex){
        		log.error(ex.getMessage(), ex);
        	}
         }else{
        	 doValid(request,response);
         }
    }
    
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        doGet(request,response);
    }
    
    public void doValid(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        String echoStr = request.getParameter("echostr");
        try{
        	if(checkSignature(request,response)){
            	response.getWriter().write(echoStr);
            }
        }catch(NoSuchAlgorithmException e){
        	response.getWriter().write("NoSuchAlgorithmException");
        }
    }
    
    private boolean checkSignature(HttpServletRequest request, HttpServletResponse response) throws NoSuchAlgorithmException
    {
        String signature = request==null?"d28fa75a425aeb3bbd0792ef457cce8ccdc1965d":request.getParameter("signature");
        String timestamp = request==null?"1394066340":request.getParameter("timestamp");
        String nonce = request==null?"1394213303":request.getParameter("nonce");
        String token = TOKEN;
        String[] tmpArr = {token, timestamp, nonce};
        Arrays.sort(tmpArr);
        String tmpStr = "";
        for(int i=0;i<tmpArr.length;i++){
        	tmpStr=tmpStr+tmpArr[i];
        }
        MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
        messageDigest.update(tmpStr.getBytes());
        tmpStr=getFormattedText(messageDigest.digest());
        if(tmpStr.equals(signature)){
            return true;
        }else{
            return false;
        }
    }
    
    private static String getFormattedText(byte[] bytes) {
    	int len = bytes.length;
    	StringBuilder buf = new StringBuilder(len * 2);
    	// 把密文转换成十六进制的字符串形式
    	for (int j = 0; j < len; j++) {
    		buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
    		buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
    	}
    	return buf.toString();
    }
    
    public void doResponseMsg(HttpServletRequest request, HttpServletResponse response) throws Exception
    {
    	BufferedReader br = request.getReader();
    	String line="";
    	StringBuffer sb=new StringBuffer();
    	while((line = br.readLine()) != null){
    		sb.append(line);
    	}
        String postStr = new String(sb.toString().getBytes("ISO8859-1"),"UTF-8");
        log.debug(postStr);
        if (postStr!=null&&!"".equals(postStr)){//微信平台发送过来正常数据
        	String result="";
            SAXReader reader= new SAXReader();
            Document document=reader.read(new ByteArrayInputStream(postStr.getBytes("UTF-8")));
            result=transmitText(document, "系统异常!");
        }else{
        	response.getWriter().write("");
        }
    }
    
    private String getText(Document document,String key){
    	Node node=document.selectSingleNode("/xml/"+key);
    	return node==null?"":node.getText();
    }
    
    private String receiveLocation(Document document)
    {
        /*$url = "http://api100.duapp.com/weather2/?appkey=".$object->ToUserName."&lat=".$object->Location_X."&lng=".$object->Location_Y;
        $output = file_get_contents($url);
        $content = json_decode($output, true);*/
    	String url = "http://api100.duapp.com/weather2/?appkey="+getText(document,"ToUserName")+"&lat="+getText(document,"Location_X")+"&lng="+getText(document,"Location_Y");
        String result = url;
        return result;
    }
    
    private String receiveVoice(Document document)
    {
        String url = "http://api100.duapp.com/joke/?appkey="+getText(document,"ToUserName");
        /*$output = file_get_contents($url);
        $content = json_decode($output, true);
        transmitText($object, $content)*/
        String result = transmitText(document, url);
        return result;
    }
    
    private String transmitText(Document document, String content)
    {
        String textTpl = "<xml><ToUserName><![CDATA["+getText(document,"FromUserName")+"]]></ToUserName>";
        textTpl=textTpl+"<FromUserName><![CDATA["+getText(document,"ToUserName")+"]]></FromUserName>";
        textTpl=textTpl+"<CreateTime>"+System.currentTimeMillis()+"</CreateTime>";
        textTpl=textTpl+"<MsgType><![CDATA[text]]></MsgType>";
        textTpl=textTpl+"<Content><![CDATA["+content+"]]></Content></xml>";
        return textTpl;
    }

	public Map getDataModel() {
		return dataModel;
	}

	public void setDataModel(Map dataModel) {
		this.dataModel = dataModel;
	}
}